package cn.wolfcode.car.business.service.impl;

import cn.wolfcode.car.business.domain.BpmnInfo;
import cn.wolfcode.car.business.domain.CarPackageAudit;
import cn.wolfcode.car.business.domain.ServiceItem;
import cn.wolfcode.car.business.mapper.ServiceItemMapper;
import cn.wolfcode.car.business.query.ServiceItemQuery;
import cn.wolfcode.car.business.service.IBpmnInfoService;
import cn.wolfcode.car.business.service.ICarPackageAuditService;
import cn.wolfcode.car.business.service.IServiceItemService;
import cn.wolfcode.car.common.base.page.TablePageInfo;
import cn.wolfcode.car.common.exception.BusinessException;
import cn.wolfcode.car.common.util.Convert;
import cn.wolfcode.car.shiro.ShiroUtils;
import com.alibaba.druid.sql.visitor.functions.If;
import com.github.pagehelper.PageHelper;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class ServiceItemServiceImpl implements IServiceItemService {

    @Autowired
    private ServiceItemMapper serviceItemMapper;

    @Autowired
    private ICarPackageAuditService carPackageAuditService;

    @Autowired
    private IBpmnInfoService bpmnInfoService;

    @Autowired
    private RuntimeService runtimeService;


    @Override
    public TablePageInfo<ServiceItem> query(ServiceItemQuery qo) {
        PageHelper.startPage(qo.getPageNum(), qo.getPageSize());
        return new TablePageInfo<ServiceItem>(serviceItemMapper.selectForList(qo));
    }


    @Override
    public void save(ServiceItem serviceItem) {

        //添加服务单项，只提交了有限的数据，
        // 我们需要另外处理其他的参数 创建的时间，审核状态为初始化，未上架

        serviceItem.setCreateTime(new Date());      //时间

        //判断是否为套餐类型
         if (ServiceItem.CARPACKAGE_YES.equals(serviceItem.getCarPackage())) {
            //套餐类型,需要设置审核状态为初始化
            serviceItem.setAuditStatus(ServiceItem.AUDITSTATUS_INIT);       //审核状态为：初始化

        }else {
            //不是套餐类型，为服务单项
            //需要设置为，无需审核状态
            serviceItem.setAuditStatus(ServiceItem.AUDITSTATUS_NO_REQUIRED);    //无需审核
        }

        //需要设置为未上架状态
        serviceItem.setSaleStatus(ServiceItem.SALESTATUS_OFF);      //未上架

        serviceItemMapper.insert(serviceItem);
    }

    @Override
    public ServiceItem get(Long id) {
        return serviceItemMapper.selectByPrimaryKey(id);
    }


    @Override
    public void update(ServiceItem serviceItem) {


        ServiceItem oldServiceItem = serviceItemMapper.selectByPrimaryKey(serviceItem.getId());


        //编辑操作，需要判断,第一个不为审核状态中的服务不可修改
        if (ServiceItem.AUDITSTATUS_AUDITING.equals(oldServiceItem.getAuditStatus())) {
            //审核状态中的，抛出异常
            throw new BusinessException("服务项目正在审核中,不可修改");
        }
        if (ServiceItem.SALESTATUS_ON.equals(oldServiceItem.getSaleStatus())){
            //上架状态中的，不可修改，抛出异常
            throw new BusinessException("上架服务项目不能修改，请下架后再修改");
        }

        //如果是状态为审核通过的，修改的话，需要重新设置为初始状态
        serviceItem.setAuditStatus(ServiceItem.AUDITSTATUS_INIT);

        serviceItemMapper.updateServiceItem(serviceItem);
    }

    @Override
    public void deleteBatch(String ids) {
        Long[] dictIds = Convert.toLongArray(ids);
        for (Long dictId : dictIds) {
            serviceItemMapper.deleteByPrimaryKey(dictId);
        }
    }

    @Override
    public List<ServiceItem> list() {
        return serviceItemMapper.selectAll();
    }

    @Override
    public void saleOn(Long id) {
        //上架方法，需要判断两类，
        // 一类是项目单项，直接上架，修改上架状态码，
        //二是套餐：先判断审核状态，只有审核通过才可以上架，
        ServiceItem serviceItem = serviceItemMapper.selectByPrimaryKey(id);

        //需要限制，当用户在地址栏传递id,没有该id的信息导致空指针异常，并且，如果是已经上架的，直接抛异常
        if (serviceItem == null || ServiceItem.SALESTATUS_ON.equals(serviceItem.getSaleStatus())) {
            throw new BusinessException("参数异常");
        }



        //如果是项目单项
        if (ServiceItem.CARPACKAGE_NO.equals(serviceItem.getCarPackage())){
            //直接上架
            serviceItemMapper.changeSaleStatus(id,ServiceItem.SALESTATUS_ON);
            return;
        }else {
            //这是套餐，需要判断是否为审核通过
            if (ServiceItem.AUDITSTATUS_APPROVED.equals(serviceItem.getAuditStatus())) {
                serviceItemMapper.changeSaleStatus(id,ServiceItem.SALESTATUS_ON);
                return;
            }else {
                //审核没通过，抛出异常
                throw new BusinessException("只有在审核通过的情况下，才可以上架");
            }
        }

    }

    @Override
    public void saleOff(Long id) {
        //下架操作，
        ServiceItem serviceItem = serviceItemMapper.selectByPrimaryKey(id);

        //需要限制，当用户在地址栏传递id,没有该id的信息导致空指针异常，并且，如果是已经下架的，直接抛异常
        if (serviceItem == null || ServiceItem.SALESTATUS_OFF.equals(serviceItem.getSaleStatus())) {
            throw new BusinessException("参数异常");
        }
        serviceItemMapper.changeSaleStatus(id,ServiceItem.SALESTATUS_OFF);
    }


    @Override
    public void startAudit(Long id, Long bpmnInfoId,Long director, Long finance, String info) {

        //进行业务逻辑判断，需要为套餐类型，并且状态初始化，才可以发起审核
        ServiceItem serviceItem = serviceItemMapper.selectByPrimaryKey(id);

        if (serviceItem == null || ServiceItem.CARPACKAGE_NO.equals(serviceItem.getCarPackage())
        || !ServiceItem.AUDITSTATUS_INIT.equals(serviceItem.getSaleStatus())){
            //如果服务单项为空，不是套餐，或者不是初始化状态，抛出异常
            throw new BusinessException("参数异常");
        }


        //创建CarPackageAudit对象，往历史表中插入审核历史数据
        CarPackageAudit audit = new CarPackageAudit();

        //判断用户是否指定了店长的审核人
        if (director == null){
            throw new BusinessException("必须指定店长审核人");
        }

        //进行数据的插入，但是数据不完整，需要额外进行处理
        //还需要处理的数据有，注意带取过来的参数
        //设置审核人id
        audit.setAuditorId(director);
        //审核流程定义的id
        audit.setBpmnInfoId(bpmnInfoId);
        //创建时间
        audit.setCreateTime(new Date());
        //当前审核人
        audit.setCreator(ShiroUtils.getLoginName());
        //设置备注
        audit.setInfo(info);
        //设置服务单项
        audit.setServiceItemId(serviceItem.getId());
        audit.setServiceItemInfo(serviceItem.getInfo());
        audit.setServiceItemPrice(serviceItem.getDiscountPrice());
        //设置当前状态为审核中
        audit.setStatus(CarPackageAudit.STATUS_IN_ROGRESS);

        //插入数据库
        carPackageAuditService.save(audit);

        //修改服务单项中的状态为审核中
        serviceItemMapper.changeStatus(id,ServiceItem.AUDITSTATUS_AUDITING);

        //启动流程实例，设置审核参数
        // 设置店长审核人，财务审核人
        Map<String, Object> map = new HashMap<>();
        //设置审核人的id,可以查询到审核人的信息
        if (director !=null){
            map.put("director",director);
        }

        if (finance != null){
            //财务不为空，设置财务审核人，一样设置id，可以查询到财务审核人的信息
            map.put("finance",finance);
        }

        //activiti7中是不使用BigDecimal进行大小比较的，此处使用Long
        //这一步的操作主要是为了，把数据添加进审批历史表中
        map.put("discountPrice",serviceItem.getDiscountPrice().longValue());

        //设置业务标识 businessKey
        //这样做的目的是为了关联业务，从流程任务可以获取到businessKey
        //从businessKey 可以获取到历史审核信息
        String businessKey =  audit.getId().toString();

        //启动流程实例前的准备工作
        BpmnInfo bpmnInfo = bpmnInfoService.get(bpmnInfoId);

        //通过runtimeService启动流程实例
        //参数：流程定义key  ，业务key，流程参数
        ProcessInstance processInstance = runtimeService
                .startProcessInstanceByKey(bpmnInfo.getActProcessKey(),
                        audit.getId().toString(), map);

        //更新审核历史表中，流程实例id
        audit.setInstanceId(processInstance.getId());

        //因为上面已经查出来audit，所以此时修改没有问题
        carPackageAuditService.update(audit);

    }

    @Override
    public void changeStatus(Long id, Integer auditStatus) {
        serviceItemMapper.changeStatus(id,auditStatus);
    }

}
